#import "KawaAdPlugin.h"
#import <BUAdSDK/BUAdSDK.h>
#import "MobAdBannerPlatformView.h"
#import "MobAdNativeView.h"

@interface KawaAdPlugin()<BUSplashAdDelegate,BUNativeExpressRewardedVideoAdDelegate,BUNativeExpresInterstitialAdDelegate,FlutterStreamHandler>

@property (nonatomic, strong) BUNativeExpressRewardedVideoAd *rewardVideoAd;
@property (nonatomic, strong) BUSplashAdView *splashAd;
@property (nonatomic, strong) BUNativeExpressInterstitialAd *intersAd;
@property (nonatomic, strong) FlutterResult callback;
@property (nonatomic, weak) NSObject<FlutterPluginRegistrar> *registrar;
@property (nonatomic, copy) NSString *userId;
@property (nonatomic, strong) UIView *contentView;
@end

@implementation KawaAdPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"com.mob.adsdk/method" binaryMessenger:[registrar messenger]];
    KawaAdPlugin *instance = [[KawaAdPlugin alloc] init];
    instance.registrar = registrar;
    [registrar addMethodCallDelegate:instance channel:channel];
    MobAdBannerPlatformViewFactory *f = [[MobAdBannerPlatformViewFactory alloc] initWithRegistrar:registrar];
    [registrar registerViewFactory:f withId:@"com.mob.adsdk/banner"];
    MobAdNativeViewFactory *nativeView = [[MobAdNativeViewFactory alloc] initWithRegistrar:registrar];
    [registrar registerViewFactory:nativeView withId:@"com.mob.adsdk/native"];
}

- (void)dealloc {
    NSLog(@"ad plugin -> dealloc");
}

- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {

    NSLog(@"ad plugin -> handleMethodCall:%@, args:%@", call.method, call.arguments);

    // 建立监听
    NSString *channelId = call.arguments[@"_channelId"];
    if ([channelId isKindOfClass:[NSNumber class]]) {
        NSString *channel = [NSString stringWithFormat:@"com.mob.adsdk/event_%@", channelId];
        FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:channel binaryMessenger:[_registrar messenger]];
        [eventChannel setStreamHandler:self];
    }

    // 调用方法
    if ([call.method isEqualToString:@"setUserId"]) {
        NSString *uid = call.arguments[@"userId"];
        if ([uid isKindOfClass:[NSString class]] && uid.length) {
            self.userId = uid;
        } else {
            self.userId = nil;
        }

    }else if ([call.method isEqualToString:@"showSplashAd"]) {
        NSString *groupId = call.arguments[@"unitId"];
        CGRect frame = [UIScreen mainScreen].bounds;
        if (self.splashAd != nil) {
            self.splashAd = nil;
        }
        self.splashAd = [[BUSplashAdView alloc] initWithSlotID:groupId frame:frame];
        self.splashAd.delegate = self;
        [self.splashAd loadAdData];
        UIViewController *vc = [KawaAdPlugin findCurrentShowingViewController];
        CGFloat width = [UIScreen mainScreen].bounds.size.width;
        CGFloat height = [UIScreen mainScreen].bounds.size.height;
        self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
        [vc.view addSubview:self.contentView];
        
        NSString *launchImage = call.arguments[@"launchImage"];
        if (launchImage) {
            NSString *path = [self.registrar lookupKeyForAsset:launchImage];
            NSLog(@"%@",path);
            UIImage *image = [UIImage imageNamed:path inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];
            if (image != NULL) {
                CGFloat imageHeight = image.size.height/image.size.width * width;
                UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, width, imageHeight)];
                imageView.image = image;
                imageView.contentMode = UIViewContentModeScaleAspectFill;
                [self.contentView addSubview:imageView];
            }
        }
        [self.contentView addSubview:self.splashAd];
        NSString *bottomImg = call.arguments[@"bottomImage"];
        if (bottomImg) {
            NSString *path = [self.registrar lookupKeyForAsset:bottomImg];
            NSLog(@"%@",path);
            UIImage *image = [UIImage imageNamed:path inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];
            if (image != NULL) {
                CGFloat imageHeight = image.size.height/image.size.width * width;
                UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, height - imageHeight, width, imageHeight)];
                imageView.image = image;
                imageView.contentMode = UIViewContentModeScaleAspectFill;
                [self.contentView addSubview:imageView];
            }
        }

    } else if ([call.method isEqualToString:@"showInterstitialAd"]) {
        NSString *groupId = call.arguments[@"unitId"];
        if (self.intersAd != nil) {
            self.intersAd = nil;
        }
        CGFloat width = [call.arguments[@"width"] floatValue];
        CGFloat height = [call.arguments[@"height"] floatValue];
        self.intersAd = [[BUNativeExpressInterstitialAd alloc] initWithSlotID:groupId adSize:CGSizeMake(width, height)];
        self.intersAd.delegate = self;
        [self.intersAd loadAdData];

    } else if (([call.method isEqualToString:@"showRewardVideoAd"])) {
        NSString *groupId = call.arguments[@"unitId"];
        // 生成激励视频加载器
        if (self.rewardVideoAd != nil) {
            self.rewardVideoAd = nil;
        }
        BURewardedVideoModel *model = [[BURewardedVideoModel alloc] init];
        model.userId = self.userId;
        self.rewardVideoAd = [[BUNativeExpressRewardedVideoAd alloc] initWithSlotID:groupId rewardedVideoModel:model];
        self.rewardVideoAd.delegate = self;
        [self.rewardVideoAd loadAdData];
    }else if ([call.method isEqualToString:@"initSdk"]){
        [BUAdSDKManager setAppID:call.arguments[@"appId"]];
//        [BUAdSDKManager setIsPaidApp:false];
        [BUAdSDKManager setLoglevel:BUAdSDKLogLevelDebug];
        result(@(1));
    }else if ([call.method isEqualToString:@"sdkIsInit"]){
        result(@(true));
    } else {
        result(FlutterMethodNotImplemented);
    }
}

- (FlutterError* _Nullable)onListenWithArguments:(NSString *_Nullable)arguments
                                       eventSink:(FlutterEventSink)events {
    NSLog(@"ad plugin -> onListen:%@", arguments);
    if (events) {
        self.callback = events;
    }

//    if ([arguments isEqualToString:@"rewardVideo"]) {
//        if (events) {
//            self.rvCallback = events;
//        }
//    } else if ([arguments isEqualToString:@"interstitial"]) {
//        if (events) {
//            self.interCallback = events;
//        }
//    }

    return nil;
}

- (FlutterError *)onCancelWithArguments:(id)arguments {
    NSLog(@"ad plugin -> onCancelListen:%@", arguments);
    return nil;
}



// 获取当前显示的 UIViewController
+ (UIViewController *)findCurrentShowingViewController {
    //获得当前活动窗口的根视图
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
    UIViewController *currentShowingVC = [self findCurrentShowingViewControllerFrom:vc];
    return currentShowingVC;
}

+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc
{
    // 递归方法 Recursive method
    UIViewController *currentShowingVC;
    if ([vc presentedViewController]) {
        // 当前视图是被presented出来的
        UIViewController *nextRootVC = [vc presentedViewController];
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];

    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        // 根视图为UITabBarController
        UIViewController *nextRootVC = [(UITabBarController *)vc selectedViewController];
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];

    } else if ([vc isKindOfClass:[UINavigationController class]]){
        // 根视图为UINavigationController
        UIViewController *nextRootVC = [(UINavigationController *)vc visibleViewController];
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];

    } else {
        // 根视图为非导航类
        currentShowingVC = vc;
    }

    return currentShowingVC;
}

#pragma mark -- 闪屏回调

- (void)splashAdDidLoad:(BUSplashAdView *)splashAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdLoad"});
    }
}

/**
 This method is called when splash ad material failed to load.
 @param error : the reason of error
 */
- (void)splashAd:(BUSplashAdView *)splashAd didFailWithError:(NSError * _Nullable)error{
    NSLog(@"%@",error);
    if (self.callback) {
        self.callback(@{@"event":@"onError",@"error":error.localizedDescription});
        self.callback(FlutterEndOfEventStream);
        [self.contentView removeFromSuperview];
        self.callback = nil;
    }
}

/**
 This method is called when splash ad slot will be showing.
 */
- (void)splashAdWillVisible:(BUSplashAdView *)splashAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdShow"});
    }
}

/**
 This method is called when splash ad is clicked.
 */
- (void)splashAdDidClick:(BUSplashAdView *)splashAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdClicked"});
    }
}

/**
 This method is called when splash ad is closed.
 */
- (void)splashAdDidClose:(BUSplashAdView *)splashAd{
    if (self.callback) {
        self.callback(@{@"event":@"onClosed"});
        self.callback(FlutterEndOfEventStream);
        [self.contentView removeFromSuperview];
        self.callback = nil;
    }
}
/**
 This method is called when another controller has been closed.
 @param interactionType : open appstore in app or open the webpage or view video ad details page.
 */
- (void)splashAdDidCloseOtherController:(BUSplashAdView *)splashAd interactionType:(BUInteractionType)interactionType{
    if (self.callback) {
        self.callback(@{@"event":@"onClosed"});
        self.callback(FlutterEndOfEventStream);
        [self.contentView removeFromSuperview];
        self.callback = nil;
    }
}

/**
 This method is called when spalashAd skip button  is clicked.
 */
- (void)splashAdDidClickSkip:(BUSplashAdView *)splashAd{
    if (self.callback) {
        self.callback(@{@"event":@"onClosed"});
        self.callback(FlutterEndOfEventStream);
        [self.contentView removeFromSuperview];
        self.callback = nil;
    }
}

/**
 This method is called when spalashAd countdown equals to zero
 */
- (void)splashAdCountdownToZero:(BUSplashAdView *)splashAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdTickOver"});
        self.callback(FlutterEndOfEventStream);
        [self.contentView removeFromSuperview];
        self.callback = nil;
    }
}

#pragma mark --激励视频

/**
 This method is called when video ad material loaded successfully.
 */
- (void)nativeExpressRewardedVideoAdDidLoad:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdLoad"});
    }
}

/**
 This method is called when video ad materia failed to load.
 @param error : the reason of error
 */
- (void)nativeExpressRewardedVideoAd:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd didFailWithError:(NSError *_Nullable)error{
    if (self.callback) {
        self.callback(@{@"event":@"onError",@"error":error.localizedDescription});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}
/**
 This method is called when cached successfully.
 For a better user experience, it is recommended to display video ads at this time.
 And you can call [BUNativeExpressRewardedVideoAd showAdFromRootViewController:].
 */
- (void)nativeExpressRewardedVideoAdDidDownLoadVideo:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd{
    [self.rewardVideoAd showAdFromRootViewController:[KawaAdPlugin findCurrentShowingViewController]];
    if (self.callback) {
        self.callback(@{@"event":@"onVideoCached"});
    }
}
/**
 This method is called when a nativeExpressAdView failed to render.
 @param error : the reason of error
 */
- (void)nativeExpressRewardedVideoAdViewRenderFail:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd error:(NSError *_Nullable)error{
    if (self.callback) {
        self.callback(@{@"event":@"onError",@"error":error.localizedDescription});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}
/**
 This method is called when video ad slot has been shown.
 */
- (void)nativeExpressRewardedVideoAdDidVisible:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdShow"});
    }
}

/**
 This method is called when video ad is closed.
 */
- (void)nativeExpressRewardedVideoAdDidClose:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdClose"});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}

/**
 This method is called when video ad is clicked.
 */
- (void)nativeExpressRewardedVideoAdDidClick:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdClick"});
    }
}

/**
 This method is called when the user clicked skip button.
 */
- (void)nativeExpressRewardedVideoAdDidClickSkip:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdClose"});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}

/**
 This method is called when video ad play completed or an error occurred.
 @param error : the reason of error
 */
- (void)nativeExpressRewardedVideoAdDidPlayFinish:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd didFailWithError:(NSError *_Nullable)error{
    if (error == NULL) {
        if (self.callback) {
            self.callback(@{@"event":@"onVideoComplete"});
        }
    }else{
        self.callback(@{@"event":@"onError",@"error":error.localizedDescription});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
    
}

/**
 Server verification which is requested asynchronously is succeeded. now include two v erify methods:
      1. C2C need  server verify  2. S2S don't need server verify
 @param verify :return YES when return value is 2000.
 */
- (void)nativeExpressRewardedVideoAdServerRewardDidSucceed:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd verify:(BOOL)verify{
    if (self.callback) {
        self.callback(@{@"event":@"onReward"});
    }
}
/**
  Server verification which is requested asynchronously is failed.
  @param rewardedVideoAd express rewardVideo Ad
  @param error request error info
 */
- (void)nativeExpressRewardedVideoAdServerRewardDidFail:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd error:(NSError *_Nullable)error{
    if (self.callback) {
        self.callback(@{@"event":@"onError",@"error":error.localizedDescription});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}

/**
 This method is called when another controller has been closed.
 @param interactionType : open appstore in app or open the webpage or view video ad details page.
 */
- (void)nativeExpressRewardedVideoAdDidCloseOtherController:(BUNativeExpressRewardedVideoAd *)rewardedVideoAd interactionType:(BUInteractionType)interactionType{
    if (self.callback) {
        self.callback(@{@"event":@"onAdClose"});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}

#pragma mark --插屏广告
/**
 This method is called when interstitial ad material loaded successfully.
 */
- (void)nativeExpresInterstitialAdDidLoad:(BUNativeExpressInterstitialAd *)interstitialAd{
    [self.intersAd showAdFromRootViewController:[KawaAdPlugin findCurrentShowingViewController]];
    if (self.callback) {
        self.callback(@{@"event":@"onAdLoad"});
    }
}

/**
 This method is called when interstitial ad material failed to load.
 @param error : the reason of error
 */
- (void)nativeExpresInterstitialAd:(BUNativeExpressInterstitialAd *)interstitialAd didFailWithError:(NSError * __nullable)error{
    if (self.callback) {
        self.callback(@{@"event":@"onError",@"error":error.localizedDescription});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}

- (void)nativeExpresInterstitialAdRenderSuccess:(BUNativeExpressInterstitialAd *)interstitialAd{
    [interstitialAd showAdFromRootViewController:[KawaAdPlugin findCurrentShowingViewController]];
}


/**
 This method is called when a nativeExpressAdView failed to render.
 @param error : the reason of error
 */
- (void)nativeExpresInterstitialAdRenderFail:(BUNativeExpressInterstitialAd *)interstitialAd error:(NSError * __nullable)error{
    if (self.callback) {
        self.callback(@{@"event":@"onError",@"error":error.localizedDescription});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}

/**
 This method is called when interstitial ad slot will be showing.
 */
- (void)nativeExpresInterstitialAdWillVisible:(BUNativeExpressInterstitialAd *)interstitialAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdShow"});
    }
}

/**
 This method is called when interstitial ad is clicked.
 */
- (void)nativeExpresInterstitialAdDidClick:(BUNativeExpressInterstitialAd *)interstitialAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdClick"});
    }
}

/**
 This method is called when interstitial ad is closed.
 */
- (void)nativeExpresInterstitialAdDidClose:(BUNativeExpressInterstitialAd *)interstitialAd{
    if (self.callback) {
        self.callback(@{@"event":@"onAdClose"});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}

/**
 This method is called when another controller has been closed.
 @param interactionType : open appstore in app or open the webpage or view video ad details page.
 */
- (void)nativeExpresInterstitialAdDidCloseOtherController:(BUNativeExpressInterstitialAd *)interstitialAd interactionType:(BUInteractionType)interactionType{
    if (self.callback) {
        self.callback(@{@"event":@"onAdClose"});
        self.callback(FlutterEndOfEventStream);
        self.callback = nil;
    }
}
@end
